
#ifndef _THREAD_H__INCLUDED_
#   error do not include this file directly, include Thread.h
#endif

#ifndef  _THREAD_IMPL_
#define  _THREAD_IMPL_

#include "Utility/RefPtr.h"
#include "FunctionBinder.h"

namespace nebula { namespace utility {

class thread_impl_base
{
public:
	virtual ~thread_impl_base() {};
	virtual int start() = 0;
	virtual int join()  = 0;
	virtual int start_in_background(Thread *) = 0;
};

template<typename thread_proc_t>
class thread_impl : public thread_impl_base
{
	typedef thread_impl<thread_proc_t> this_type;

private:
	thread_proc_t   _proc;
	ref_ptr<ThreadDetail> _handle;

public:
	thread_impl(thread_proc_t& thread_proc) :
		_proc(thread_proc)
	{
	}

public:
	int start() {
		if (_handle.get() == 0)
			_handle.reset(new ThreadDetail(thread_agent, this));

		return _handle->start();
	}

	int join() {
		if (_handle.get() == 0)
			return -1;
		return _handle->join();
	}

	int start_in_background(Thread *thread) {
		if (_handle.get() == 0)
			_handle.reset(new ThreadDetail(thread_agent, this));

		return _handle->start_in_background(thread);
	}

private:
	static void thread_agent(void* para)
	{
		this_type* p = static_cast<this_type*>(para);
		if (p) {
			p->_proc();
		}
	}

};

template<typename proc_t>
thread_impl<proc_t>*
make_thread_impl(proc_t proc)
{
	return new thread_impl<proc_t>(proc);
}

}} // namespace nebula::utility

#endif
